{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Chapter 2: Drawing with 2D Vectors"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2.1 Picturing 2D Vectors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "from vector_drawing import *"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "source": [
    "dino_vectors = [(6,4), (3,1), (1,2), (-1,5), (-2,5), (-3,4), (-4,4),\n",
    "    (-5,3), (-5,2), (-2,2), (-5,1), (-4,0), (-2,1), (-1,0), (0,-3),\n",
    "    (-1,-4), (1,-4), (2,-3), (1,-2), (3,-1), (5,1)\n",
    "]\n",
    "\n",
    "draw(\n",
    "    Points(*dino_vectors)\n",
    ")"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "source": [
    "draw(\n",
    "    Points(*dino_vectors),\n",
    "    Segment((6,4),(3,1))\n",
    ")"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** Draw the dinosaur with the dots connected by constructing a `Polygon` object with the `dino_vectors` as its vertices."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "source": [
    "draw(\n",
    "    Points(*dino_vectors),\n",
    "    Polygon(*dino_vectors)\n",
    ")"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE** Draw the vectors `[(x,x**2) for x in range(-10,11)]` as points (dots) using the draw function.  What is the result?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "source": [
    "draw(\n",
    "    Points(*[(x,x**2) for x in range(-10,11)]),\n",
    "    grid=(1,10),\n",
    "    nice_aspect_ratio=False # don't require x scale to match y scale\n",
    ")"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Plane Vector Arithmetic"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "source": [
    "def add(v1,v2):\n",
    "    return (v1[0] + v2[0], v1[1] + v2[1])"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "source": [
    "dino_vectors2 = [add((-1.5,-2.5), v) for v in dino_vectors]"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "source": [
    "draw(\n",
    "    Points(*dino_vectors, color=blue),\n",
    "    Polygon(*dino_vectors, color=blue),\n",
    "    Points(*dino_vectors2, color=red),\n",
    "    Polygon(*dino_vectors2, color=red)\n",
    ")"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "source": [
    "arrows = [Segment(tip,tail,color=black) for (tip,tail) in\n",
    "         zip(dino_vectors2, dino_vectors)]\n",
    "draw(\n",
    "    Points(*dino_vectors, color=blue),\n",
    "    Polygon(*dino_vectors, color=blue),\n",
    "    Points(*dino_vectors2, color=red),\n",
    "    Polygon(*dino_vectors2, color=red),\n",
    "    *arrows\n",
    ")"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Vector components and lengths"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "source": [
    "from math import sqrt\n",
    "def length(v):\n",
    "    return sqrt(v[0]**2 + v[1]**2) "
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Subtraction, displacement, and distance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "source": [
    "draw(\n",
    "    Points((2,2), (-1,3)),\n",
    "    Segment((2,2), (-1,3), color=red)\n",
    ")"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**MINI-PROJECT:** You can add any number of vectors together by summing all of their $x$-coordinates and all of their $y$-coordinates.  For instance the four-fold sum (1,2) + (2,4) + (3,6) + (4,8) has $x$-component 1 + 2 + 3 + 4 = 10 and $y$-component 2 + 4 + 6 + 8 = 20, making the result (10,20).  Implement a revised add function that takes any number of vectors as arguments."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "source": [
    "def add(*vectors):\n",
    "    return (sum([v[0] for v in vectors]), sum([v[1] for v in vectors]))"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** Write a function translate(translation, vectors) that takes in a translation vector and a list of input vectors and returns a list of the input vectors all translated by the translation vector. For instance, `translate((1,1), [(0,0), (0,1,), (-3,-3)])` should return `[(1,1),(1,2),(-2,-2)]`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "source": [
    "def translate(translation, vectors):\n",
    "    return [add(translation, v) for v in vectors]\n",
    "\n",
    "translate((1,1), [(0,0), (0,1,), (-3,-3)])"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**MINI-PROJECT:** Write a Python function using vector addition to show 100 simultaneous and non-overlapping copies of the dinosaur.  This shows the power of computer graphics: imagine how tedious it would be to specify all 2,100 coordinate pairs by hand!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "source": [
    "def hundred_dinos():\n",
    "    translations = [(12*x,10*y) \n",
    "                    for x in range(-5,5) \n",
    "                    for y in range(-5,5)]\n",
    "    dinos = [Polygon(*translate(t, dino_vectors),color=blue)\n",
    "                for t in translations]\n",
    "    draw(*dinos, grid=None, axes=None, origin=None)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "scrolled": true
   },
   "source": [
    "hundred_dinos()"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** What vector in the dino_vectors list has the longest length?  Use the Python length function to compute the answer quickly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "source": [
    ">>> max(dino_vectors, key=length)\n",
    "(6, 4)"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** Suppose a vector $\\vec{w}$ has coordinates $(2 ,3)$.  What are the approximate coordinates of the scalar multiple $\\pi \\cdot \\vec{w}$?  Draw an approximation of the original vector and the new vector."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "source": [
    "from math import sqrt, pi\n",
    "\n",
    "w = (sqrt(2),sqrt(3))\n",
    "w_scaled = (pi * sqrt(2), pi * sqrt(3))"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "source": [
    "w_scaled"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "source": [
    "draw(\n",
    "    Arrow(w_scaled, color=red),\n",
    "    Arrow(w, color=black)\n",
    ")"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** Write a python function `scale(s, v)` that multiplies the input vector `v` by the input scalar `s`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "source": [
    "def scale(scalar,v):\n",
    "    return (scalar * v[0], scalar * v[1])"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**MINI-PROJECT:** Suppose $\\vec{u} = (-1,1)$ and $\\vec{v} = (1,1)$ and suppose $r$ and $s$ are real numbers.  Specifically, let’s assume $-1 < r < 1$ and $-3 < s < 3$.  \n",
    "\n",
    "Where are the possible points on the plane where the vector $r \\cdot \\vec{u} + s \\cdot \\vec{v}$ could end up?  \n",
    "\n",
    "Note: the order of operations is the same for vectors as it is for numbers: we assume scalar multiplication is carried out first, and then vector addition (unless parentheses specify otherwise)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "source": [
    "from random import uniform\n",
    "u = (-1,1)\n",
    "v = (1,1)\n",
    "def random_r():\n",
    "    return uniform(-3,3)\n",
    "def random_s(): \n",
    "    return uniform(-1,1)\n",
    "possibilities = [add(scale(random_r(), u), scale(random_s(), v)) \n",
    "                 for i in range(0,500)]\n",
    "draw(\n",
    "    Points(*possibilities)\n",
    ")"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** Write a Python function `subtract(v1,v2)` that returns the result of `v1` minus `v2`, where the inputs and output are tuples of coordinates as we’ve seen so far."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "source": [
    "def subtract(v1,v2):\n",
    "    return (v1[0] - v2[0], v1[1] - v2[1])"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** Write a Python function `distance(v1,v2)` that returns the distance between two input vectors (noting that the subtract function from the previous exercise already gives the displacement).  \n",
    "\n",
    "Write another Python function `perimeter(vectors)` that takes a list of vectors as an argument and returns the sum of distances from each vector to the next, including the distance from the last vector to the first.  What is the perimeter of the polygon defined by `dino_vectors`?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "source": [
    "def distance(v1,v2):\n",
    "    return length(subtract(v1,v2))"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "source": [
    "def perimeter(vectors):\n",
    "    distances = [distance(vectors[i], vectors[(i+1)%len(vectors)])\n",
    "                    for i in range(0,len(vectors))]\n",
    "    return sum(distances)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "source": [
    "# sanity check with a square\n",
    "square = [(1,0),(1,1),(0,1),(0,0)]\n",
    "draw(Polygon(*square), grid=(0.2,0.2), axes=None)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "source": [
    "# should be 1+1+1+1=4\n",
    "perimeter(square)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "source": [
    "perimeter(dino_vectors)"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**MINI-PROJECT:** Let $\\vec{u}$ be the vector $(1,2)$.  Suppose there is another vector, $\\vec{v}$, with positive integer coordinates $(n, m)$ such that $n > m$, and having distance $13$ from $\\vec{u}$.  What is the displacement from $\\vec{u}$ to $\\vec{v}$?  Hint: you can use Python to search for the vector $\\vec{v}$."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**SOLUTION:** We only need to search possible integer pairs (n,m) where n is within 13 units of 1 and m is within 13 units of -1."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "source": [
    "for n in range(-12,15):\n",
    "    for m in range(-14, 13):\n",
    "        if distance((n,m), (1,-1)) == 13 and n > m > 0:\n",
    "            print((n,m))"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Angles and trigonometry in the plane"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Radians and trigonometry in python"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "source": [
    "from math import tan\n",
    "tan(45) # tangent of 45 radians, not degrees"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "source": [
    "from math import tan, pi\n",
    "tan(pi/4) # now this is the tangent of pi/4 radians = 45 degrees "
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "source": [
    "from math import sin, cos\n",
    "def to_cartesian(polar_vector):\n",
    "    length, angle = polar_vector[0], polar_vector[1]\n",
    "    return (length*cos(angle), length*sin(angle))"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "source": [
    "# Verify that 5 units @ 37 degrees takes us to (4,3)\n",
    "angle = 37*pi/180\n",
    "to_cartesian((5,angle))"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {},
   "source": [
    "from math import asin\n",
    "sin(1)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "source": [
    "asin(0.8414709848078965)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "source": [
    "# trying to find an angle with sin = 3/sqrt(13)\n",
    "from math import sqrt\n",
    "asin(3/sqrt(13))"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "source": [
    "from math import acos\n",
    "acos(-2/sqrt(13))"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "source": [
    "cos(2.1587989303424644)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "source": [
    "-2/sqrt(13)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "source": [
    "sin(2.1587989303424644)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "source": [
    "3/sqrt(13)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "source": [
    "from math import atan2\n",
    "atan2(3,-2)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "source": [
    "def to_polar(vector):\n",
    "    x, y = vector[0], vector[1]\n",
    "    angle = atan2(y,x)\n",
    "    return (length(vector), angle)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "source": [
    "to_polar((1,0))"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "source": [
    "to_polar((-2,3))"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** Confirm that the vector given by cartesian coordinates (-1.34,2.68) has length approximately 3, as expected."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "source": [
    "length((-1.34,2.68))"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** What is $116.57^\\circ$ in radians?  Use Python to compute the tangent of this angle, and confirm that it is close to $-2$ as we saw above."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**SOLUTION:** $116.57^\\circ · (1 \\text{rad} / 57.296^\\circ) = 2.035 \\text{rad}.$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "source": [
    "tan(2.035)"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** Locate the angle $10\\pi/6$.  Do you expect the values of $\\cos(10\\pi/6)$ and $\\sin(10\\pi/6)$ to be positive or negative?  Use Python to calculate their values and confirm."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**SOLUTION:** The angle $\\pi/6$ is one third of a quarter-turn, so $10\\pi/6$ is less than a quarter turn short of a full rotation.  This means that it points \"down and to the right\".  The cosine should be positive and the sine should be negative, since distance in this direction corresponds with positive horizontal displacement and negative vertical displacement."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "source": [
    "sin(10*pi/6)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "source": [
    "cos(10*pi/6)"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** The following list comprehension creates 1000 points in polar coordinates.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "metadata": {},
   "source": [
    "polar_coords = [(cos(5*x*pi/500.0), 2*pi*x/1000.0) for x in range(0,1000)]"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In Python code, convert them to cartesian coordinates, and connect them in a closed loop with line segments to draw a picture."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "source": [
    "polar_coords = [(cos(x*pi/100.0), 2*pi*x/1000.0) for x in range(0,1000)]\n",
    "vectors = [to_cartesian(p) for p in polar_coords]\n",
    "draw(Polygon(*vectors, color=green))"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** Find the angle to get to the point (-2,3) by “guess-and-check”.  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "source": [
    "# we want to make guesses between pi/2 and pi\n",
    "pi, pi/2"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "source": [
    "tan(1.8)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "source": [
    "tan(2.5)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "source": [
    "tan(2.2)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "source": [
    "tan(2.1)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "source": [
    "tan(2.15)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {},
   "source": [
    "tan(2.16)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {},
   "source": [
    "tan(2.155)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {},
   "source": [
    "tan(2.156)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "metadata": {},
   "source": [
    "tan(2.157)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "source": [
    "tan(2.158)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "source": [
    "# we conclude the angle is between 2.158 and 2.159.\n",
    "tan(2.159)"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:**  Find another point in the plane with the same tangent as $\\theta$, that is $-3/2$.  Use Python’s implementation of the arctangent function, `math.atan`, to find the value of this angle."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "source": [
    "from math import atan"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "source": [
    "atan(-3/2)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "source": [
    "# this is the direction to the point (2,-3).  \n",
    "# tan(-3/2) = tan(-1.5) = tan(3/-2)\n",
    "draw(Arrow((2,-3)), Points((2,-3)))"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** Without using Python, what are polar coordinates corresponding to the cartesian coordinates $(1,1)$ and $(1,-1)$?  Once you’ve found the answers, use to_polar to check your work.\n",
    "\n",
    "**SOLUTION:** The answers should be $(\\sqrt{2},\\pi/4)$ and $(\\sqrt{2},-\\pi/4)$."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "source": [
    "to_polar((1,1))"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "metadata": {},
   "source": [
    "to_polar((1,-1))"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "metadata": {},
   "source": [
    "#compare to\n",
    "(sqrt(2), pi/4)"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "metadata": {},
   "source": [
    "(sqrt(2), -pi/4)"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Transforming collections of vectors"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "metadata": {},
   "source": [
    "rotation_angle = pi/4\n",
    "\n",
    "dino_polar = [to_polar(v) for v in dino_vectors]\n",
    "dino_rotated_polar = [(l,angle + rotation_angle) for l,angle in dino_polar]\n",
    "dino_rotated = [to_cartesian(p) for p in dino_rotated_polar]\n",
    "\n",
    "draw(\n",
    "    Polygon(*dino_vectors, color=gray),\n",
    "    Polygon(*dino_rotated, color=red)\n",
    ")"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** Create a `rotate(angle, vectors)` function which takes an array of input vectors in cartesian coordinates and returns them by the specified angle (counterclockwise or clockwise according to whether the angle is positive or negative). "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "metadata": {},
   "source": [
    "def rotate(angle, vectors):\n",
    "    polars = [to_polar(v) for v in vectors]\n",
    "    return [to_cartesian((l, a+angle)) for l,a in polars]"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Combining vector transformations"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "source": [
    "new_dino = translate((8,8), rotate(5 * pi/3, dino_vectors))"
   ],
   "outputs": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**EXERCISE:** Create a function `polygon(n)` which returns cartesian coordinates of a regular $n$-sided polygon (that is, having all angles and side lengths equal).  For instance, `polygon(7)` could produce vectors defining a heptagon."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "metadata": {},
   "source": [
    "def regular_polygon(n):\n",
    "    return [to_cartesian((1, 2*pi*k/n)) for k in range(0,n)]"
   ],
   "outputs": []
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "source": [
    "draw(\n",
    "    Polygon(*regular_polygon(7))\n",
    ")"
   ],
   "outputs": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
